// add custom jest matchers from jest-dom
import '@testing-library/jest-dom';

// custom render
import { render, screen } from '@app-nextmesh-env/nextmesh/utils';

// the component to test
import JSONFormatForm from './JSONFormatForm';
import { makeDefaultForm } from './components/utils';

// 主要测试 json 是否能正确渲染界面，暂时不考虑交互（用户输入等）

const customTest = (
  name: string,
  object: any,
  text: string | RegExp,
  debug = false,
) => {
  test(name, () => {
    render(
      <JSONFormatForm
        readonly={false}
        formData={makeDefaultForm(object)}
        formFormat={object}
        handleInputChange={() => {
          // do nothing
        }}
      />,
    );
    expect(screen.getByRole('alert')).toHaveTextContent(text);
    if (debug) {
      screen.debug();
    }
  });
};

describe('JSONFormatForm', () => {
  // 不合法的JSON对象（Object）
  const commonCases: any[] = [[], [1], [{}], 0, 123, '', false, true, null];
  const notPlainObjects = [...commonCases, 'invalid', ['string']];
  for (const notPlainObject of notPlainObjects) {
    customTest(
      `not plain object: ${JSON.stringify(notPlainObject)}`,
      notPlainObject,
      /格式错误/i,
    );
  }

  // 子字段不合法
  for (const notPlainObject of notPlainObjects) {
    const json = { Selection: notPlainObject };
    customTest(
      `children has not plain object: ${JSON.stringify(json)}`,
      json,
      /格式错误/i,
    );
  }

  // 没有Type
  const noType: any = {
    Selection: {},
  };
  customTest('no Type', noType, /缺少Type字段/i);

  // 无效的Type
  const invalidTypes: any = [...notPlainObjects, {}, { a: true }];
  for (const invalidType of invalidTypes) {
    customTest(
      `invalid Type: ${JSON.stringify(invalidType)}`,
      { Selection: { Type: invalidType } },
      /无效的Type类型|格式错误/i,
      false,
    );
  }

  // 各种Type类型的json格式
  const arrayJsons = [
    {
      Type: 'Arrayb',
    },
    {
      Type: 'Arrayi',
    },
    {
      Type: 'Arrayd',
    },
    {
      Type: 'xArrayd',
    },
  ];
  const typeJsons: any = [
    {
      Type: 'double',
    },
    {
      Type: 'int',
    },
    ...arrayJsons,
  ];
  // 表格类型
  const makeTabluarJsons = (column: object) => [
    {
      Type: 'tabular',
      Column1: {
        ...column,
      },
    },
  ];
  // 无效的Unit
  const invalidUnits: any = [...commonCases, {}, { a: true }];
  for (const typeJson of typeJsons) {
    for (const invalidUnit of invalidUnits) {
      const json = { Selection: { ...typeJson, Unit: invalidUnit } };
      customTest(
        `invalid Unit: ${JSON.stringify(json)}`,
        json,
        /格式错误/i,
        false,
      );
    }
  }
  for (const invalidUnit of invalidUnits) {
    const json = makeTabluarJsons({ Unit: invalidUnit });
    customTest(
      `invalid Unit: ${JSON.stringify(json)}`,
      json,
      /格式错误/i,
      false,
    );
  }

  // 无效的Default
  const invalidDoubleDefaults: any[] = [[], [1], [{}], '', false, true, null];
  for (const invalidDefault of invalidDoubleDefaults) {
    const json = {
      Selection: {
        Type: 'double',
        Default: invalidDefault,
      },
    };
    customTest(
      `invalid double Default: ${JSON.stringify(json)}`,
      json,
      /格式错误/i,
      false,
    );
  }
  const invalidIntDefaults: any[] = [...invalidDoubleDefaults, 123.1];
  for (const invalidDefault of invalidIntDefaults) {
    const json = {
      Selection: {
        Type: 'int',
        Default: invalidDefault,
      },
    };
    customTest(
      `invalid int Default: ${JSON.stringify(json)}`,
      json,
      /格式错误/i,
      false,
    );
  }
  const invalidArrayDefaults: any[] = [['true'], [{}], '', false, true, null];
  for (const typeJson of arrayJsons) {
    for (const invalidDefault of invalidArrayDefaults) {
      const json = {
        Selection: {
          ...typeJson,
          Default: invalidDefault,
        },
      };
      customTest(
        `invalid array Default: ${JSON.stringify(json)}`,
        json,
        /格式错误/i,
        false,
      );
    }
  }
  for (const invalidDefault of invalidArrayDefaults) {
    const json = makeTabluarJsons({ Default: invalidDefault });
    customTest(
      `invalid tabluar Default: ${JSON.stringify(json)}`,
      json,
      /格式错误/i,
      false,
    );
  }
  // type类型是JSONObject时，Default必须是JSONObject的键之一
  const invalidTypeDefaultJson = {
    Selection: { Type: { a: {} }, Default: 'b' },
  };
  customTest(
    `invalid type Default: ${JSON.stringify(invalidTypeDefaultJson)}`,
    invalidTypeDefaultJson,
    /格式错误/i,
    false,
  );

  const json = {
    Selection: {
      Type: 'Volume',
    },
    Force: {
      Type: 'Arrayd',
      Unit: 'N',
      Default: [0.0, 0.0, 0.0],
    },
  };
  test('loads and displays JSON format form', async () => {
    render(
      <JSONFormatForm
        readonly={false}
        formData={makeDefaultForm(json)}
        formFormat={json}
        handleInputChange={(name, value) => {
          // do nothing
        }}
      />,
    );
    expect(screen.queryAllByRole('alert').length).toBe(0);
  });
});
